package com.earthea.scaffold.common.config.security;

import com.earthea.cache.CacheService;
import com.earthea.scaffold.common.config.security.context.AuthenticationContextHolder;
import com.earthea.scaffold.common.constant.Constants;
import com.earthea.scaffold.common.entity.BaseDataRsp;
import com.earthea.scaffold.common.enums.CacheEnum;
import com.earthea.scaffold.common.exception.UserPasswordRetryLimitExceedException;
import com.earthea.scaffold.domain.LoginUser;
import com.earthea.scaffold.domain.SysFile;
import com.earthea.scaffold.domain.User;
import com.earthea.scaffold.system.service.SysFileService;
import com.earthea.scaffold.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * 用户验证处理
 */
@Slf4j
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Autowired
    private BCryptPasswordEncoder encoder;

    @Value(value = "${app.user.password.maxRetryCount}")
    private int maxRetryCount;

    @Value(value = "${app.user.password.lockTime}")
    private int lockTime;

    @Autowired
    private CacheService cacheService;

    @Autowired
    private SysFileService sysFileService;

    @Override
    public UserDetails loadUserByUsername(String loginName) throws UsernameNotFoundException {
        User user = userService.selectByUser(loginName);
        if (Objects.isNull(user)) {
            log.info("登录用户：{} 不存在.", loginName);
            throw new UsernameNotFoundException("用户不存在/密码错误");
        }
        validate(user);

        LoginUser loginUser = new LoginUser(user);
        BaseDataRsp<SysFile> sysFileBaseDataRsp = sysFileService.selectById(user.getAvatarId());
        if (sysFileBaseDataRsp.isSuccess()) {
            loginUser.setAvatar(sysFileBaseDataRsp.getData().getFilePath());
        }
        return loginUser;
    }

    public void validate(User user) {
        Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
        String username = usernamePasswordAuthenticationToken.getName();
        String password = usernamePasswordAuthenticationToken.getCredentials().toString();
        String key = CacheEnum.PWD_ERR_CNT.getCacheKey(username);
        int retryCount = NumberUtils.toInt(cacheService.get(key), 0);

        if (retryCount >= maxRetryCount) {
            throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
        }

        if (!encoder.matches(password, user.getPassword())) {
            retryCount = retryCount + 1;
            cacheService.setex(key, String.valueOf(retryCount), lockTime);
            throw new UsernameNotFoundException("用户不存在/密码错误");
        } else {
            cacheService.del(key);
        }
    }

}
